package com.wangijun.yuan.admin.config;

import cn.dev33.satoken.exception.DisableServiceException;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.core.util.StrUtil;
import com.wangijun.yuan.admin.base.CommonResult;
import com.wangijun.yuan.admin.base.AuthErrEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局异常捕获
 * 顺序不可写错，接口越高地拦截，就越排在最后
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {


    @ExceptionHandler(NotLoginException.class)
    CommonResult<?> handlerNotLoginException(NotLoginException e) {
        // 如果是未登录异常
        log.error("错误", e);
        log.info("未登录异常: {}", e.getMessage());
        return CommonResult.fail(AuthErrEnum.NOT_LOGIN);
    }

    @ExceptionHandler(NotRoleException.class)
    CommonResult<?> handlerNotRoleException(NotRoleException e) {
        // 如果是角色异常
        log.error("错误", e);
        log.info("角色异常: {}", e.getMessage());
        return CommonResult.fail(e.getMessage());
    }

    @ExceptionHandler(NotPermissionException.class)
    CommonResult<?> handlerNotPermissionException(NotPermissionException e) {
        // 如果是权限异常
        log.error("错误", e);
        log.info("权限异常: {}", e.getMessage());
        return CommonResult.fail(e.getMessage());
    }

    @ExceptionHandler(DisableServiceException.class)
    CommonResult<?> handlerDisableLoginException(DisableServiceException e) {
        // 如果是被封禁异常
        log.error("错误", e);
        log.info("封禁异常: {}", e.getMessage());
        return CommonResult.fail(e.getMessage());
    }

    /**
     * 校验错误拦截处理
     *
     * @param e 错误信息集合
     * @return 错误信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    CommonResult<?> validationBodyException(MethodArgumentNotValidException e) {
        log.error("错误", e);
        //对校验错误信息进行封装，并输出到日志
        BindingResult result = e.getBindingResult();
        StringBuilder errorMessage = new StringBuilder();
        if (result.hasErrors()) {
            List<ObjectError> errors = result.getAllErrors();
            errors.forEach(p -> {
                FieldError fieldError = (FieldError) p;
                log.error("数据校验错误 : object{" + fieldError.getObjectName() + "},field{" + fieldError.getField() +
                        "},errorMessage{" + fieldError.getDefaultMessage() + "}");
                errorMessage.append(fieldError.getDefaultMessage()).append("; ");
            });
        }
        return CommonResult.fail(errorMessage.toString());
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    CommonResult<?> handleException(HttpRequestMethodNotSupportedException e) {
        log.error("错误", e);
        log.error("请求方式不支持: {}", e.getMessage(), e);
        return CommonResult.fail(":传入请求错误不支持" + e.getMethod() + "'请求");
    }

    /**
     * 请求的数据格式错误的处理
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    CommonResult<?> handleException(HttpMessageNotReadableException e) {
        log.error("错误", e);
        log.error("请求的数据格式错误的处理: {}", e.getMessage(), e);
        return CommonResult.fail("传入数据格式错误");
    }

    /**
     * 通用异常
     */
    @ExceptionHandler(RuntimeException.class)
    CommonResult<?> handlerRuntimeException(RuntimeException e) {
        log.error("错误", e);
        log.error("通用异常: {}", e.getMessage());
        return CommonResult.fail(StrUtil.format("通用异常: {}", e.getMessage()));
    }

    /**
     * 顶级异常
     */
    @ExceptionHandler(Exception.class)
    CommonResult<?> handlerException(Exception e) {
        log.error("错误", e);
        log.error("顶级异常: {}", e.getMessage());
        return CommonResult.fail(StrUtil.format("顶级异常: {}", e.getMessage()));
    }
}
